// **********************************************************
// *************   ArduPLAY Default Firmware   **************
// ***   ArduPLAY Designed by Melih Karakelle on  2011     **
// **          an Arudino based Display system             **
// **       This Source code licensed under GPL            **
// **********************************************************
// Version Number     : 1.01
// Latest Code Update : 2011-10-17
// Supported Hardware : ArduPLAY board (store.flytron.com)
// Project Forum      : http://forum.flytron.com/viewforum.php?f=7
// Google Code Page   : http://code.google.com/p/arduplay/
// **********************************************************

// ******************** ArduPLAY DEVELOPERS ****************** 
// Melih Karakelle (http://www.flytron.com) (forum nick name: Flytron)
//

 /*
  LCD Pins:
 * LCD RS pin to digital pin 5
 * LCD Enable pin to digital pin 6
 * LCD D4 pin to digital pin 7
 * LCD D5 pin to digital pin 8
 * LCD D6 pin to digital pin 9
 * LCD D7 pin to digital pin 10
 */

#include <LiquidCrystal.h>
#include <EEPROM.h>    


//  50A/1024 = 0.04882
//50A INA139 sensor
//#define current_factor 0.04882

//50A ADS756 sensor
#define current_factor 0.09764
#define current_offset 512
#define total_watt_factor  0.00027777
#define rf_factor 2.2

#define buttonPin A3
#define Voltage_Sensor_Pin A0 
#define Current_Sensor_Pin A1
#define Buzzer 12

#define total_menu 6
#define menu_name_1 "Voltmeter"
#define menu_name_2 "Wattmeter"
#define menu_name_3 "RF Meter"
#define menu_name_4 "Temperature Sensor"
#define menu_name_5 "RPM Sensor"
#define menu_name_6 "GPS Mode"


int voltage_adc = 0;
int max_voltage_adc;
int min_voltage_adc;
int current_adc;

float voltage_value;
float max_voltage_value;
float min_voltage_value;

float total_watt_value;
float watt_value;
float current_value;


int rf_offset_value = 0;
float max_rf_watt = 0;

unsigned long time,old_time;
int rec_count = 0;

//String menu_names[10] ;
byte menu_number = 3; // default menu
byte button_pressed = 0;


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(5, 6, 7, 8, 9, 10);

void setup() {
  
  pinMode(buttonPin, INPUT); 
  pinMode(Buzzer, OUTPUT); 
  digitalWrite(Buzzer, HIGH); 
  digitalWrite(buttonPin, HIGH); 
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.setCursor(0,0);
  lcd.print(" ArduPLAY v1.01 ");
  lcd.setCursor(0,1);
  lcd.print(" by flytron.com ");
  
  max_voltage_adc = (EEPROM.read(0)*256)+ EEPROM.read(1);
  min_voltage_adc = (EEPROM.read(2)*256)+ EEPROM.read(3);
  
  total_watt_value = EEPROM_readFloat(10);
  
  delay(100);
  digitalWrite(Buzzer, LOW); 
  delay(3000);
  
  menu_number = EEPROM.read(100);
  if (menu_number>total_menu) menu_number = 1;
}

void loop() {
  
  time = millis();
    
  switch (menu_number) 
                 {
                  case 1:
                    voltage_mode();
                    break;
                  case 2:
                    watt_mode();
                    break;
                  case 3:
                    rf_mode();
                    break;
                  case 4:
                    temp_mode();
                    break;
                  case 5:
                    rpm_mode();
                    break;  
                  case 6:
                    gps_mode();
                    break;    
                  default: 
                    voltage_mode(); // default mode
                  }
                  
 menu();
     
}


void menu()
{
  if (digitalRead(buttonPin)==LOW) 
     {
     digitalWrite(Buzzer, HIGH); 
     delay(100);
     digitalWrite(Buzzer, LOW); 
   
     button_pressed = 1; // if you press the button for shorter than 2 seconds, this is only a button press, not a mode change.  
          
     byte button_counter = 0;
     while(digitalRead(buttonPin)==LOW)
         {
         button_counter++;
         delay(100);
         
         if (button_counter>20) // the button pressed more than 2 seconds.
             {
             button_pressed = 0; // disable button pressed mode, because the button pressed too long for mode changes.  
             button_counter = 0;  
             menu_number++;
             if (menu_number>total_menu) menu_number = 1;
             
             EEPROM.write(100,menu_number);
              
             lcd.setCursor(0,0);
             
             switch (menu_number) 
                 {
                  case 1:
                    lcd.print(menu_name_1);
                    break;
                  case 2:
                    lcd.print(menu_name_2);
                    break;
                  case 3:
                    lcd.print(menu_name_3);
                    break;
                  case 4:
                    lcd.print(menu_name_4);
                    break;
                  case 5:
                    lcd.print(menu_name_5);
                    break;  
                  default: 
                    lcd.print("Out of List");
                  }
             fill_line(); 
             lcd.setCursor(0,1);
             lcd.print("Selected...");
             fill_line(); 
             digitalWrite(Buzzer, HIGH); 
             delay(100);
             digitalWrite(Buzzer, LOW);
             }
         }
 
          
     }   
  
} 



void fill_line(){
  lcd.print("                ");
}

//=====================================================================================
//=== VOLTAGE MODE ===
//  (5v*4.1333)/1024 = 0.0202
#define voltage_factor 0.0202 

void voltage_mode()
{
if (time> old_time+100) // 1hz 
  {
  old_time = time; 
  
  voltage_adc = analogRead(Voltage_Sensor_Pin);
  current_adc = analogRead(Current_Sensor_Pin)-current_offset;
  
  if (button_pressed==1) 
        {
        min_voltage_adc = 1024;
        max_voltage_adc = 0;
        button_pressed = 0;  
        }  
      
    
  if (voltage_adc > max_voltage_adc) 
     {
      max_voltage_adc = voltage_adc;
      EEPROM.write(0, max_voltage_adc / 256);
      EEPROM.write(1, max_voltage_adc % 256);
     }

  if (voltage_adc < min_voltage_adc) 
     {
      min_voltage_adc = voltage_adc;
      EEPROM.write(2, min_voltage_adc / 256);
      EEPROM.write(3, min_voltage_adc % 256);
     }
     

  
  
    voltage_value =      (voltage_factor* float(voltage_adc));
    max_voltage_value =  (voltage_factor* float(max_voltage_adc));
    min_voltage_value =  (voltage_factor* float(min_voltage_adc));
    
    current_value =      (current_factor* float(current_adc));
    
    lcd.setCursor(0, 0);
    
    lcd.print(voltage_value);
    lcd.print("v ");
    
    lcd.print(current_value);
    lcd.print("A");
    fill_line();
    
    lcd.setCursor(0,1);
    lcd.print(min_voltage_value);
    lcd.print("v ");
    lcd.print(max_voltage_value);
    lcd.print("v ");
    fill_line();
  
 }

}
  


//====================================================================================
//===  WATT MODE  ===


void watt_mode()
{
 
   if (time> old_time+1000) // 1hz 
     {
     old_time = time; 
     rec_count++;
  
     voltage_adc = analogRead(Voltage_Sensor_Pin);
     current_adc = analogRead(Current_Sensor_Pin)-current_offset;
     if (button_pressed==1) 
        {
        total_watt_value = 0;
        EEPROM_writeFloat(10,0);
        button_pressed = 0;  
        }
    
     voltage_value =      (voltage_factor* float(voltage_adc));
     current_value =      (current_factor* float(current_adc));
  
     watt_value = (float) current_value * voltage_value;
  
     total_watt_value += total_watt_factor*watt_value;
     
     if (rec_count>10) // record after every 100 seconds
        {
        EEPROM_writeFloat(10, total_watt_value); 
        rec_count = 0;
        }
     
     lcd.setCursor(0,0);
     lcd.print(voltage_value);
     lcd.print("v  ");
     lcd.print(current_value);
     lcd.print("A");
     fill_line();
     
     lcd.setCursor(0,1);
     lcd.print(watt_value);
     lcd.print("W  ");
     lcd.print(total_watt_value);
     lcd.print("W");
     fill_line();
             
             
     }
  
}


//====================================================================================
//===  RF MODE  ===



void rf_mode()
{
 
  if (time> old_time+10) // 100hz 
     {
     old_time = time; 
          
     int rf_adc = analogRead(Current_Sensor_Pin) -rf_offset_value;
     float rf_value =      (rf_factor* float(rf_adc));
     
     if (rf_value>max_rf_watt) max_rf_watt = rf_value;
     
     if (button_pressed==1) 
        {
        max_rf_watt = 0;
        button_pressed = 0;  
        rf_offset_value = analogRead(Current_Sensor_Pin);
        }
     
     
     
     lcd.setCursor(0,0);
     lcd.print(int(rf_value), DEC);
     lcd.print("mW  ");
     lcd.print(int(max_rf_watt), DEC);
     lcd.print("mW");
     fill_line();
     
     lcd.setCursor(0,1);
     lcd.print("RAW:");
     lcd.print(rf_adc, DEC);     
     fill_line();
     }
  
 
}


//====================================================================================
//===  TEMPERATURE MODE  ===
float temp_value,max_temp,min_temp,fahrenheit_value;

void temp_mode()
{
   if (time> old_time+100) // 1hz 
     {
     old_time = time; 
     
     #define temp_factor 0.5 // 10mV/˚C for LM35DZ Analog linear temperature sensor 
     
     int temp_adc = analogRead(Current_Sensor_Pin);
     float temp_value =  (temp_factor* float(temp_adc));
     
     if (button_pressed==1) 
        {
        max_temp = 0;
        min_temp = 1024;
        button_pressed = 0;  
        }
     if (temp_value>max_temp) max_temp = temp_value;
     
     fahrenheit_value = (1.8*temp_value)+32;
     
     lcd.setCursor(0,0);
     lcd.print(temp_value);
     lcd.print(" Celcius");
     fill_line();
     
     
     lcd.setCursor(0,1);
     lcd.print(fahrenheit_value);
     lcd.print(" Fahrenheit");
     fill_line();
     }
}

//====================================================================================
//===  RPM MODE  ===
long rpm_value,max_rpm,min_rpm,rpm_time,rpm_old_time;
unsigned char rpm_ = 0;

void rpm_mode()
{
   rpm_time = micros();
   
   if (analogRead(Current_Sensor_Pin)<200) rpm_ = 1; 
       else
   if (rpm_==1)
       {
       rpm_ = 0;
       rpm_value = 60000000/(rpm_time - rpm_old_time);
       rpm_old_time = rpm_time;
       
       if (rpm_value>max_rpm) max_rpm = rpm_value;
       
        lcd.setCursor(0,0);
        lcd.print(rpm_value);
        lcd.print(" rpm");
        fill_line();
        
        lcd.setCursor(0,1);
        lcd.print(max_rpm);
        lcd.print(" rpm max");
        fill_line();
       } 
     {

     if (button_pressed==1) 
        {
        max_rpm = 0;
        min_rpm = 1024;
        button_pressed = 0;  
        }
     
     

     
     }
}

//====================================================================================
//===  GPS MODE  ===

void gps_mode()
{
 
   if (time> old_time+1000) // 1hz 
     {
     old_time = time; 
     
     lcd.setCursor(0,0);
     lcd.print("GPS Positions");
     fill_line();
     
     lcd.setCursor(0,1);
     lcd.print("81.22.99.42");
     fill_line();
     }
}


//================================
//Funstions
void EEPROM_writeFloat(int ee, float value)
{
    byte* p = (byte*)(void*)&value;
    for (int i = 0; i < sizeof(value); i++)
	  EEPROM.write(ee++, *p++);
}

float EEPROM_readFloat(int ee)
{
    float value = 0.0;
    byte* p = (byte*)(void*)&value;
    for (int i = 0; i < sizeof(value); i++)
	  *p++ = EEPROM.read(ee++);
    return value;
} 
